package com.lheia.tool

import com.lheia.tool.thread.DownloadThread
import org.springframework.context.annotation.ComponentScan
import org.springframework.stereotype.Component

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.CountDownLatch;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;


/**
 *
 * 文件下载管理类
 */


@Component
 class DownLoadManager {

     private static final Logger LOGGER = LoggerFactory.getLogger(DownLoadManager.class);
    @Autowired
    TaskExecutor taskExecutor
     /**
      *
      * 每个线程下载的字节数
      */
     private long unitSize = 1000 * 1024;

     private CloseableHttpClient httpClient;
     private Long starttimes;
     private Long endtimes;
     void setUp() throws Exception {
         starttimes = System.currentTimeMillis();
         System.out.println("测试开始....");
     }
     void tearDown() throws Exception {
         endtimes = System.currentTimeMillis();
         System.out.println("测试结束!!");
         System.out.println("********************");
         System.out.println("下载总耗时:" + (endtimes - starttimes) / 1000 + "s");
         System.out.println("********************");
     }

     DownLoadManager() {
         System.out.println("初始化测试类....");
         PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
         cm.setMaxTotal(100);
         httpClient = HttpClients.custom().setConnectionManager(cm).build();
     }
    /**
     *
     * 启动多个线程下载文件
     */
     void doDownload(String remoteFileUrl,String localPath,String fileName) throws IOException {
         //println("远程文件名称：" + remoteFileUrl)
        // println("本地文件名称：" + ToolString.getURLDecoderString(fileName))
         long fileSize = this.getRemoteFileSize(remoteFileUrl)
         this.createFile(localPath + fileName, fileSize);
         Long threadCount = (fileSize / unitSize) + (fileSize % unitSize != 0 ? 1 : 0);
         Long offset = 0;
         CountDownLatch end = new CountDownLatch(threadCount.intValue());
         if (fileSize <= unitSize ) {// 如果远程文件尺寸小于等于unitSize
             DownloadThread downloadThread = new DownloadThread(remoteFileUrl,
                     localPath + fileName, offset, fileSize, end, httpClient);
             taskExecutor.execute(downloadThread);
             println("当前活动线程数："+ taskExecutor.getActiveCount());
             println("核心线程数："+ taskExecutor.getCorePoolSize());
             println("总线程数："+ taskExecutor.getPoolSize());
             println("最大线程池数量"+taskExecutor.getMaxPoolSize());
             println("线程处理队列长度"+taskExecutor.getThreadPoolExecutor().getQueue().size());
         } else {// 如果远程文件尺寸大于unitSize
             for (int i = 1; i < threadCount; i++ ) {
                 DownloadThread downloadThread = new DownloadThread(remoteFileUrl, localPath + fileName, offset, unitSize, end, httpClient);
                 taskExecutor.execute(downloadThread);
                 offset = offset + unitSize;
             }
             if (fileSize % unitSize != 0) {// 如果不能整除，则需要再创建一个线程下载剩余字节
                 DownloadThread downloadThread = new DownloadThread(remoteFileUrl, localPath + fileName, offset, fileSize - unitSize * (threadCount - 1), end, httpClient);
                 taskExecutor.execute(downloadThread);
             }
         }
         try {
             end.await();
         } catch (InterruptedException e) {
             LOGGER.error("DownLoadManager exception msg:{}", ExceptionUtils.getFullStackTrace(e));
             e.printStackTrace();
         }
     }
     /**
      *
      * 获取远程文件尺寸
      */

     private long getRemoteFileSize(String remoteFileUrl) throws IOException {
         long fileSize = 0;
         HttpURLConnection httpConnection = (HttpURLConnection) new URL(remoteFileUrl).openConnection();
         httpConnection.setRequestMethod("HEAD");
         int responseCode = httpConnection.getResponseCode();
         if (responseCode/100 == 4 ) {
             LOGGER.debug("Web服务器响应错误!");
             return 0;
         }
         String sHeader;
         for (int i = 1; ; i++) {
             sHeader = httpConnection.getHeaderFieldKey(i);
             if (sHeader != null && sHeader.equals("Content-Length") ) {
                 println("文件大小ContentLength:"
                         + httpConnection.getContentLength());
                 fileSize = Long.parseLong(httpConnection
                         .getHeaderField(sHeader));
                 break;
             }
         }
         return fileSize;

     }

/**
 *
 * 创建指定大小的文件
 */

     private void createFile(String fileName, long fileSize) throws IOException {
         File newFile = new File(fileName);
         if(!newFile.parentFile.exists()){
             newFile.parentFile.mkdirs()
         }
         RandomAccessFile raf = new RandomAccessFile(newFile, "rw");
         raf.setLength(fileSize);
         raf.close();
     }


     TaskExecutor getTaskExecutor() {
         return taskExecutor;
     }
    @Autowired
      void setTaskExecutor(TaskExecutor taskExecutor) {
         this.taskExecutor = taskExecutor;
     }
 }